#!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*-
##--------------------------------------------------------------------------##
##
## Copyright (C) 1998-2003 Markus Oberhumer <markus@oberhumer.com>
## Copyright (C) 2003 Mt. Hood Playing Card Co.
## Copyright (C) 2005-2010 Skomoroh <skomoroh@users.sourceforge.net>
## Copyright (C) 2010-2013 Jeremy Austin-Bardo <tjaustinbardo@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##-- G01 -- S02 ------------------------------------------------------------##
__all__ = []

from .. import pilelib as stack
from ..formlib import Layout
from ..gamelib import info as gi, state, game
from ..packlib import place

GT, SL = gi.GT, gi.SL
StackWrapper = stack.StackWrapper


class Labyrinth_Talon(stack.DealRowTalon):
    """
    Deal 1 card on 1st S most _row_ gap.
    """

    def deal_cards(self, sound=False):
        """
        deal_cards([sound:bool=False]) -> None

        Actual dealing, called from Game.talon_deal(). Deal cards to S most
        _row_ gap.

        :keyword boolean sound: sound fx?
        """
        top_stacks = []
        for i in range(8):
            for r in self.game.s['rows'][i::8]:
                if not r.cards:
                    top_stacks.append(r)
                    break
        return self.dealRowAvail(rows=top_stacks, sound=sound)


class Labyrinth_RowStack(stack.SingleAsDoubleClickMethod,
                         stack.BasicRowStack):
    """
    Build none. Play top when _row_ below gap.
    """

    def cardsBlock(self):
        """
        cardsBlock() -> bool

        Check if pile is blocked by _row_ pile below with a card.

        :return: pile is blocked?
        :rtype: boolean
        """
        if self in self.game.s['rows'][:8]:
            return False
        id_ = self.id + 8
        if id_ >= len(self.game.allstacks):
            return False
        row = self.game.allstacks[id_]
        return row in self.game.s['rows'] and row.cards


class Labyrinth(game.Game):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 48 over 6 row. Init deal 1st 8 1 card. Play top.

    _talon_
      Pile 1 W. Deal 1 card on _row_.

    _foundation_
      Pile 4 horz N. Init deal base ACE. Build up in rank by same suit. Play
      top.

    ------
    :cvar Stack _talon_: Labyrinth_Talon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: Labyrinth_RowStack
    """
    __info__ = dict(id=400, name="Labyrinth", game_type=GT.ONE_DECK |
                    GT.HIDDEN, skill_level=SL.BALANCED, decks=1, redeals=0,
                    version='0.70up')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = Labyrinth_Talon
    _foundation_ = stack.SS_Foundation
    _row_ = Labyrinth_RowStack

    def _create_game(self, rows=48, **kw):
        l, s = Layout(self), self.s
        self.table_size = (l.XM + 8 * l.XS, l.YM + l._get_stack_height(20, l.YS),)
        x, y = l.XM, l.YM,
        s['talon'] = self._talon_(x, y, game=self)
        x += 2 * l.XS
        for i in l.SUITS:
            s['foundations'].append(self._foundation_(x, y, game=self, suit=i))
            x += l.XS
        x = l.XM
        y += l.YS
        for i in range(rows / 8):
            x = l.XM
            for j in range(8):
                s['rows'].append(self._row_(x, y, game=self))
                x += l.XS
            y += l.YOFFSET
        l.defaultAll()
        return l

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] 1 ea
          - s[rows][:8] 1 ea.

        .. \_start([]) -> None
        """
        self.s['talon'].dealRow(rows=self.s['foundations'])
        self.s['talon'].dealRow(rows=self.s['rows'][:8])

    def _pack_place(self, cards):
        """
        _pack_place(cards:seq(Card ...)) -> seq(Card ...)

        Overide to return ACE on top by suit, deck for _foundation_ deal.
        """
        return place.MoveToTop(cards, place.AllAce)

    @state.move_state('fill')
    def _auto_fill(self, stack):
        if stack in self.s['rows'][:8] and not stack.cards:
            to_stack = stack
            index = self.s['rows'].index(stack) + 8
            for row in self.s['rows'][index::8]:
                if row.cards:
                    row.move_pile(1, to_stack, frames=0)
                    to_stack = row
                else:
                    break
            if not stack.cards and self.s['talon'].cards:
                self.s['talon'].dealRow(rows=[stack])


PROVIDES = [Labyrinth]